﻿using System;
using System.Collections.Generic;
using System.Data;
using System.Collections;
using System.Windows.Forms;
using System.IO;

using XISoft.AppCreator.Util.ConfigHelper.DBConfig;
using XISoft.AppCreator.Util.Common;
using XISoft.AppCreator.TplEngine.Syntax;
using XISoft.AppCreator.Util.ConfigHelper.TplConfig;
using XISoft.AppCreator.TplEngine.ITpl;
using XISoft.AppCreator.TplEngine.XITpl;

namespace XISoft.AppCreator.TplEngine
{
    public class TplEntry : MessageHelper
    {
        private  String basePath = String.Empty;
        private  DataSet ds = null;

        
        private const String Name = "Name", inPath = "inPath", outPath = "outPath";
        private readonly String TplPath = Application.StartupPath + "\\tpls\\";
        private readonly String TargetPath = Application.StartupPath + "\\Projects\\";


        #region tpl中的变量
        public const String Entitys = "Entitys";
        public const String CurrentEntity = "currentEntity";

        public const String ProjectName = "ProjectName";
        public const String SqlUser = "SqlUser";
        public const String SqlPassword = "SqlPassword";
        public const String SqlServer = "SqlServer";
        #endregion

        #region 配置
        private readonly String _tplName;
        private readonly String _xmlFile;
        private readonly String _sqlUser;
        private readonly String _sqlPassword;
        private readonly String _sqlServer;
        #endregion

        public TplEntry(TplEngineConfigElement Config)
        {
            try
            {
                _tplName = Config.TplName;
                _xmlFile = Config.TplFile;

                _sqlUser = DBConfig.getDBConfig().UserName;
                _sqlPassword = DBConfig.getDBConfig().Password;
                _sqlServer = DBConfig.getDBConfig().Server;
            }
            catch (Exception e)
            {
                LogHelper.Trace(e);
                throw new Exception("模板配置文件错误" + e.Message);
            }

        }

        public void CodeCreate(DataSet dataSet)
        {

            basePath = TargetPath + dataSet.DataSetName.ToString();
            try
            {
                if (Directory.Exists(basePath))
                    Directory.Delete(basePath, true);

                CopyDirectory(TplPath + _tplName + "\\projects", basePath);
            }catch(IOException e)
            {
                LogHelper.Trace(e);
            }
            ReadTpl rtpl;

            ReadTplConfig();

            Hashtable listE = InitVariable(dataSet);

            List<IBaseEntity> list = listE[Entitys] as List<IBaseEntity>;


            foreach (IBaseEntity variables in list)
            {

                listE[CurrentEntity] = variables;

                foreach (DataRow dr in ds.Tables["dtD"].Rows)
                {
                    try
                    {
                        String path = TargetPath + dataSet.DataSetName.ToString() + "\\" + dr[inPath].ToString();
                        rtpl = new ReadTpl(path);
                        String newOutPath = basePath + "\\" + dr[outPath].ToString();
                        newOutPath = newOutPath.Replace("#{EntityName}", variables.EntityName.ToString());
                        rtpl.init();
                        rtpl.Variables = listE;
                        rtpl.run();
                        rtpl.WriteFile(newOutPath);
                    }
                    catch (Exception e)
                    {
                        LogHelper.Trace(e);
                    }
                }
            }
            foreach (DataRow dr in ds.Tables["dtD"].Rows)
            {
                String path = TargetPath + dataSet.DataSetName.ToString() + "\\" + dr[inPath].ToString();
                File.Delete(path);
            }
            foreach (DataRow dr in ds.Tables["dtU"].Rows)
            {
                try
                {
                    String path = TargetPath + dataSet.DataSetName.ToString() + "\\" + dr[inPath].ToString();
                    rtpl = new ReadTpl(path);
                    rtpl.init();
                    rtpl.Variables = listE;
                    rtpl.run();
                    rtpl.WriteFile(basePath + "\\" + dr[outPath].ToString());
                    File.Delete(path);
                }catch(Exception e)
                {
                    LogHelper.Trace(e);
                }

            }
        }

        private Hashtable InitVariable(DataSet dataSet)
        {
            List<IBaseEntity> list = new List<IBaseEntity>();
            Hashtable listE = new Hashtable();
            try
            {
                foreach (DataRow dr in dataSet.Tables[ModelDataDictionary.MainClass.TableName].Rows)
                {
                    if (!dr[ModelDataDictionary.MainClass.ColType].Equals("ClassObject"))
                        continue;

                    DataTable dataTable = dataSet.Tables[dr[ModelDataDictionary.MainClass.Name].ToString()];
                    IBaseEntity variables = new XIEntity();

                    variables.EntityName = dataTable.TableName.ToString();
                    variables.PropertyList = new List<IBaseProperty>();
                    variables.MethodList = new List<IBaseMethod>();

                    foreach (DataRow edr in dataTable.Rows)
                    {


                        IBaseType Type = new XIType();

                        if (edr[ModelDataDictionary.EntityTable.Type].ToString() == "Attribute")
                        {
                            IBaseProperty Property =new XIProperty();

                            Property.Name = edr[ModelDataDictionary.EntityTable.Name].ToString();
                            Type.Name = edr[ModelDataDictionary.EntityTable.DataType].ToString();
                            Property.Type = Type;
                            if (Boolean.Parse(edr[ModelDataDictionary.EntityTable.isPrimaryKey].ToString()))
                                variables.PrimaryKey = Property;
                            else
                                variables.PropertyList.Add(Property);
                        }
                        else if (edr[ModelDataDictionary.EntityTable.Type].ToString() == "Method")
                        {
                            IBaseMethod Method = new XIMethod();

                            Method.Name = edr[ModelDataDictionary.EntityTable.Name].ToString();
                            Type.Name = edr[ModelDataDictionary.EntityTable.DataType].ToString();
                            Method.Type = Type;
                            variables.MethodList.Add(Method);
                        }
                    }


                    list.Add(variables);
                    listE.Add(dr[ModelDataDictionary.EntityTable.Name].ToString(), variables);
                }
            }
            catch (Exception e)
            {
                LogHelper.Trace(e);
                throw new Exception("模板配置文件错误");
            }
            listE.Add(SqlUser, _sqlUser);
            listE.Add(SqlPassword, _sqlPassword);
            listE.Add(SqlServer, _sqlServer);
            listE.Add(Entitys, list);
            listE.Add(ProjectName, dataSet.DataSetName);
            return listE;
        }


        private void ReadTplConfig()
        {
            if (ds == null)
            {
                try
                {
                    ds = new DataSet();
                    ds.ReadXml(TplPath + _tplName + "\\" + _xmlFile);
                }
                catch (Exception e)
                {
                    LogHelper.Trace(e);
                }
            }

        }

        #region copyFiles
        static void CopyDirectory(string srcDir, string tgtDir)
        {
            DirectoryInfo source = new DirectoryInfo(srcDir);
            DirectoryInfo target = new DirectoryInfo(tgtDir);

            if (target.FullName.StartsWith(source.FullName, StringComparison.CurrentCultureIgnoreCase))
            {
                throw new Exception("父目录不能拷贝到子目录！");
            }

            if (!source.Exists)
            {
                return;
            }

            if (!target.Exists)
            {
                target.Create();
            }

            FileInfo[] files = source.GetFiles();

            for (int i = 0; i < files.Length; i++)
            {
                File.SetAttributes(files[i].FullName, FileAttributes.Normal);
                File.Copy(files[i].FullName, target.FullName + @"\" + files[i].Name, true);
            }

            DirectoryInfo[] dirs = source.GetDirectories();

            for (int j = 0; j < dirs.Length; j++)
            {
                CopyDirectory(dirs[j].FullName, target.FullName + @"\" + dirs[j].Name);
            }
        }
        #endregion
    }
}
